package com.inspire.client01.netty;

import com.inspire.client01.tank.Dir;
import com.inspire.client01.tank.Group;
import com.inspire.client01.tank.Tank;
import com.inspire.client01.tank.TankJoinMsg;
import com.inspire.common.netty.Msg;
import com.inspire.common.netty.MsgDecoder;
import com.inspire.common.netty.MsgEncoder;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.UUID;

/**
 * @author ：inspire
 * @date ：Created in 2022/8/12 14:27
 * @description：
 * @modified By：inspire
 * @version:
 */
public class Client {
    private static final Logger logger = LoggerFactory.getLogger(Client.class);

    public static final Client INSTANCE = new Client();
    private Channel channel = null;

    private Client() {}
    public void connect() {
        EventLoopGroup group = new NioEventLoopGroup(1);

        Bootstrap b = new Bootstrap();

        try {
            ChannelFuture f = b.group(group).channel(NioSocketChannel.class).handler(new ClientChannelInitializer())
                    .connect("127.0.0.1", 8888);

            f.addListener(new ChannelFutureListener() {
                @Override
                public void operationComplete(ChannelFuture future) throws Exception {
                    if (!future.isSuccess()) {
                        logger.info("not connected!");
                    } else {
                        logger.info("connected!");
                        // initialize the channel
                        channel = future.channel();
                    }
                }
            });

            f.sync();
            // wait until close
            f.channel().closeFuture().sync();
            logger.info("connection closed!");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            group.shutdownGracefully();
        }
    }

    public void send(Msg msg) {
        /*
         * 坦克对象--->编码
         */
        channel.writeAndFlush(msg);
    }

    public void closeConnect() {
		/*this.send("_bye_");
		//channel.close();
*/	}
}

class ClientChannelInitializer extends ChannelInitializer<SocketChannel> {

    /*
     * 初始化initChannel，客户端一启动，走这里
     */
    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        ch.pipeline()
                .addLast(new MsgEncoder())
                .addLast(new MsgDecoder())
                .addLast(new ClientHandler())
                .addLast(new LoggingHandler(LogLevel.INFO));
    }

}

class ClientHandler extends SimpleChannelInboundHandler<Msg> {
    private static final Logger logger = LoggerFactory.getLogger(ClientHandler.class);

    /*
     * 解码--->坦克对象
     * 每次收到消息，先解码，再走channelRead0
     */
    @Override
    public void channelRead0(ChannelHandlerContext ctx, Msg msg) throws Exception {
//        logger.info(String.valueOf(msg));
        msg.handle();
    }

    /*
     * 每个客户端一启动，先发送tank join信息，之后再发消息，使用channel.writeAndFlush(msg);
     * 坦克对象--->编码
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        ctx.writeAndFlush(new TankJoinMsg(new Tank(UUID.randomUUID(),1,1, Dir.DOWN,true, Group.GOOD)));

    }

}